import {Normalized, PreNormalized} from "./types";

function h(e, t) {
  return e - t;
}

function v(e) {
  return e.reduce(function (e, t) {
    if (e.indexOf(t) < 0) e.push(t);
    return e;
  }, []);
}

function r(e) {
  return e.reduce(function (e, t) {
    return e.concat(Array.isArray(t) ? r(t) : t);
  }, []);
}

function makeList(start, end, step) {
  let r = [];

  for (let o = start; o <= end; o += step) r.push(o);

  return r;
}

var a = /(^|[,-\/])\*($|[,-\/])/g;

function y(e, t) {
  var n = "$1" + t + "$2";
  return e.replace(a, n).replace(a, n);
}

function b(e, t) {
  let n = e.split(",").map(function (e) {
    return function (e, t) {
      var n = e ? e.match(/\d+|./g).map(function (e) {
        var t = Number(e);
        return isNaN(t) ? e : t;
      }) : [];
      var r = n[0];


      if (Number.isInteger(r)) {
        if (1 === n.length) return {
          list: [r]
        };
        if (3 === n.length && "/" === n[1] && Number.isInteger(n[2]) && 1 <= n[2]) return {
          list: makeList(r, t, n[2]),
          warnings: ["nonstandard"]
        };
        if (3 === n.length && "-" === n[1] && Number.isInteger(n[2]) && n[2] >= r) return {
          list: makeList(r, n[2], 1)
        };
        if (5 === n.length && "-" === n[1] && Number.isInteger(n[2]) && n[2] >= r && "/" === n[3] && Number.isInteger(n[4]) && 1 <= n[4]) return {
          list: makeList(r, n[2], n[4])
        };
      }

      return {
        errors: ["invalid part"]
      };
    }(e, t);
  });
  return {
    list: v(r(n.map(function (e) {
      return e.list || [];
    }))).sort(h).filter(function (e) {
      return !isNaN(e);
    }),
    errors: v(r(n.map(function (e) {
      return e.errors || [];
    }))),
    warnings: v(r(n.map(function (e) {
      return e.warnings || [];
    })))
  };
}

function g(require, module, exports) {
  return require.length && (require[0] < module || require[require.length - 1] > exports);
}

const w = /[^\d\-\/\,]/i;

export function normalize(e: PreNormalized): Normalized {
  const t = e.parts.map(function (e) {
    return e.slice(0);
  }).map(function (e) {
    // */1 => *
    return e.replace(/\*\/1(?!\d)/g, "*");
  });

  if (0 === t.length && e.originalParts.length) return {};

  const result: Normalized = {
    errors: [],
    warnings: [],
    daysAnded: false,
    minutes: [],
    dates: [],
    hours: [],
    months: [],
    weekdays: []
  };

  if (undefined !== e.daysAnded && (result.daysAnded = e.daysAnded), 5 !== t.length && result.errors.push("fields"), t[0] && t[0].length) {
    var r = y(t[0], "0-59");
    var o = b(r, 59);
    result.minutes = o.list;

    if (o.errors.length || g(result.minutes, 0, 59) || w.test(r)) {
      result.minutes = [];
      result.errors.push("minutes");
    }

    if (o.warnings.length) result.warnings.push("minutes");
  } else if (undefined === t[0]) result.errors.push("minutes");

  if (t[1] && t[1].length) {
    var a = y(t[1], "0-23");
    var u = b(a, 23);
    result.hours = u.list;

    if (u.errors.length || g(result.hours, 0, 23) || w.test(a)) {
      result.hours = [];
      result.errors.push("hours");
    }

    if (u.warnings.length) result.warnings.push("hours");
  } else if (undefined === t[1]) result.errors.push("hours");

  if (t[2] && t[2].length) {
    var i = y(t[2], "1-31");
    var s = b(i, 31);
    result.dates = s.list;

    if (s.errors.length || g(result.dates, 1, 31) || w.test(i)) {
      result.dates = [];
      result.errors.push("dates");
    }

    if (s.warnings.length) result.warnings.push("dates");
  } else if (undefined === t[2]) result.errors.push("dates");

  if (t[3] && t[3].length) {
    var c = y(t[3], "1-12");
    var l = e.originalParts[3];
    var d = b(c, 12);
    result.months = d.list;

    if (d.errors.length || g(result.months, 1, 12) || w.test(c)) {
      result.months = [];
      result.errors.push("months");
    }

    if (d.warnings.length || l && t[3] !== l && 3 < l.length && /\D/.test(l)) result.warnings.push("months");
  } else if (undefined === t[3]) result.errors.push("months");

  if (t[4] && t[4].length) {
    var m = y(t[4], "0-6");
    var f = e.originalParts[4];
    var p = b(m, 7);
    result.weekdays = v(p.list.map(function (e) {
      return 7 === e ? 0 : e;
    })).sort(h);

    if (p.errors.length || g(result.weekdays, 0, 6) || w.test(m)) {
      result.weekdays = [];
      result.errors.push("weekdays");
    }

    if (p.warnings.length || p.list.includes(7) || f && t[4] !== f && 3 < f.length && /\D/.test(f)) result.warnings.push("weekdays");
  } else if (undefined === t[4]) result.errors.push("weekdays");

  result.errors.length || delete result.errors;
  result.warnings.length || delete result.warnings;
  return result;
};
